#ifndef PROCESSOR_CHAIN_HPP
#define PROCESSOR_CHAIN_HPP
//
//  processor_chain.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2013-2014 Razvan Coca (razvan dot coca at  gmail dot com)
//
//
// chain of responsibility http://sourcemaking.com/design_patterns/chain_of_responsibility
// refined in http://isocpp.org/blog/2013/10/patterns
//

#include <vector>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/logic/tribool.hpp>
namespace patterns
{
namespace processor
{

template<typename... Args>
class chain
{
public:

    typedef boost::function<boost::logic::tribool (Args&...)>   processor_action_t;

    boost::logic::tribool operator()(Args&...args)
    {
        boost::tribool ret=boost::indeterminate;
        if(chain_.empty())return false;
        for(auto const & processor:chain_)
        {
            ret=processor(args...);
            if(!boost::logic::indeterminate(ret))break;
        }
        return ret;
    }
    template<typename processor_action>
    chain& add(processor_action&& proc)
    {
        chain_.push_back(proc);
        return *this;
    }
private:
    std::vector<processor_action_t> chain_;
};

template<typename... Args>
class simple_chain
{
public:
    typedef boost::function<bool (Args&...)>   processor_action_t;

    bool operator ()(Args&...args)
    {
        bool ret=false;
        for(auto const & processor:chain_)
            if((ret=processor(args...)))break;
        return ret;
    }
    template<typename processor_action>
    simple_chain& add(processor_action&& proc)
    {
        chain_.push_back(proc);
        return *this;
    }
private:
    std::vector<processor_action_t> chain_;
};

}//namespace processsor
}//namespace patterns
#endif // PROCESSOR_CHAIN_HPP
